package lang;


import java.util.Calendar;

import exception.JAFRuntimeException;

/**
 * 日期，默认格式为yyyy-MM-dd，不包含时间，若根据时间的毫秒数来实例化当前日期，也会自动清除其时间
 * 
 * @author 王永弟
 * @since JDK1.4
 * @copyright 广州从兴电子开发有限公司-电子渠道业务部
 * @date 2011-5-1
 */
public class Date extends AbstractDate {
	private static final long serialVersionUID = 1L;
	/**
	 * 默认的日期格式
	 */
	private static final String DEFAULT_FORMATTER = "yyyy-MM-dd";
	private static final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000;
	/**
	 * 多余的时间，减少8个小时
	 */
	private static final long MILLIS_FIRST_TIME = 8 * 60 * 60 * 1000;

	/**
	 * 初始化日期，清除时间记录
	 */
	private void init() {
		long timeInMillis = cal.getTimeInMillis();
		long time = (timeInMillis + MILLIS_FIRST_TIME) % MILLIS_PER_DAY;
		if (time != 0) {
			cal.setTimeInMillis(timeInMillis - time);
		}
	}

	/**
	 * <构造函数> 实例化日期，默认赋值系统日期
	 */
	public Date() {
		super.setFormatter(DEFAULT_FORMATTER);
		init();
	}
	
	/**
	 * <构造函数> 根据指定的yyyy-MM-dd日期字符串实例化当前日期
	 * 
	 * @param date 标准的日期字符串yyyy-MM-dd
	 */
	public Date(String date) {
		super.setFormatter(DEFAULT_FORMATTER);
		String [] dates = date.split("[-]", 3);
		cal.set(Integer.parseInt(dates[0]), Integer.parseInt(dates[1]) - 1, Integer.parseInt(dates[2]));
		init();
	}

	/**
	 * <构造函数> 根据指定的年/月/日实例化当前日期
	 * 
	 * @param year
	 *            年，大于1970
	 * @param month
	 *            月，1-12
	 * @param day
	 *            日，1-31
	 */
	public Date(int year, int month, int day) {
		super.setFormatter(DEFAULT_FORMATTER);
		cal.set(year, month - 1, day);
		init();
	}

	/**
	 * 根据毫秒数实例化当前日期，并清除时间的记录
	 * <构造函数>
	 * 
	 * @param milliseconds
	 *            毫秒数
	 */
	public Date(long milliseconds) {
		setTime(milliseconds);
	}

	@Override
	public void setTime(long milliseconds) {
		cal.setTimeInMillis(milliseconds);
		super.setFormatter(DEFAULT_FORMATTER);
		init();
	}

	/**
	 * <方法描述> 获取天，在一个月中的天数，1-31
	 * 
	 * @return 天数
	 */
	public int getDay() {
		return cal.get(Calendar.DAY_OF_MONTH);
	}

	/**
	 * <方法描述> 获取天数，在本周中的天数，1-7，默认星期日为一周的第一天
	 * 
	 * @return 天数
	 */
	public int getDayOfWeek() {
		return cal.get(Calendar.DAY_OF_WEEK);
	}

	/**
	 * <方法描述> 获取天数，在一年中的天数，1-365
	 * 
	 * @return 天数
	 */
	public int getDayOfYear() {
		return cal.get(Calendar.DAY_OF_YEAR);
	}

	/**
	 * <方法描述> 获取月份 1-12
	 * 
	 * @return 月份
	 */
	public int getMonth() {
		return cal.get(Calendar.MONTH) + 1;
	}

	/**
	 * 获取周数，在本月中的周数，1-5
	 * <方法描述>
	 * 
	 * @return 周
	 */
	public int getWeekOfMonth() {
		return cal.get(Calendar.WEEK_OF_MONTH);
	}

	/**
	 * <方法描述> 获取周数，在本年中的周数，1-53
	 * 
	 * @return 周数
	 */
	public int getWeekOfYear() {
		return cal.get(Calendar.WEEK_OF_YEAR);
	}

	/**
	 * <方法描述> 获取年数，四位的年份，yyyy
	 * 
	 * @return 年份
	 */
	public int getYear() {
		return cal.get(Calendar.YEAR);
	}

	/**
	 * <方法描述> 年份操作，可增加或减少年份
	 * 
	 * @param year
	 *            负数为减少，正数为增加
	 */
	public void addYear(int year) {
		cal.add(Calendar.YEAR, year);
	}

	/**
	 * <方法描述> 月份操作，可增加或减少月份
	 * 
	 * @param month
	 *            负数为减少，正数为增加
	 */
	public void addMonth(int month) {
		cal.add(Calendar.MONTH, month);
	}

	/**
	 * <方法描述> 日期操作，可增加或减少天数
	 * 
	 * @param day
	 *            负数为减少，正数为增加
	 */
	public void addDay(int day) {
		cal.add(Calendar.DATE, day);
	}

	/**
	 * <方法描述> 修改年份，四位的年份，yyyy
	 * 
	 * @param year
	 *            四位的年份
	 */
	public void setYear(int year) {
		cal.set(Calendar.YEAR, year);
	}

	/**
	 * <方法描述> 修改月份，1-2位的月份，值为1-12
	 * 
	 * @param month
	 *            月份
	 */
	public void setMonth(int month) {
		cal.set(Calendar.MONTH, month - 1);
	}

	/**
	 * <方法描述> 修改天数，值为1-31
	 * 
	 * @param day
	 *            天数
	 */
	public void setDay(int day) {
		cal.set(Calendar.DATE, day);
	}

	/**
	 * <方法描述> 将指定的字符串，根据指定格式，转化为日期
	 * 
	 * @param str
	 *            日期字符串
	 * @param formatter
	 *            日期对应的格式
	 * @return 日期对象
	 * @throws JAFRuntimeException
	 *             无法转换时抛出
	 */
	public static Date parse(String str, String formatter) {
		return AbstractDate.parse(str, formatter, Date.class);
	}

	/**
	 * <方法描述> 将指定的字符串，根据默认的日期格式"yyyy-MM-dd"，转化为日期
	 * 
	 * @param str
	 *            日期字符串
	 * @return 日期对象
	 * @example <调用范例>
	 */
	public static Date parse(String str) {
		return AbstractDate.parse(str, DEFAULT_FORMATTER, Date.class);
	}
}

